package k8s

import (
	"context"

	corev1 "k8s.io/api/core/v1"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	core "k8s.io/client-go/kubernetes/typed/core/v1"
)

const EventBusConfigMapChangeKey = "eventbus:k8s:configmap:change"

func NewConfigMap(cli *kubernetes.Clientset) *ConfigMap {
	return &ConfigMap{
		core: cli.CoreV1(),
	}
}

type ConfigMap struct {
	sourceWatcher[*corev1.ConfigMap]
	core core.CoreV1Interface

	didWatch bool
	watchCtx context.Context
}

func SubScribeConfigMapChange(cb ...SourceWatchCallback[*corev1.ConfigMap]) error {
	return AddSubscribers(EventBusNodeChangeKey, cb...)
}

func (s *ConfigMap) Watch(ctx context.Context, cb ...SourceWatchCallback[*corev1.ConfigMap]) error {
	if s.didWatch {
		return SubScribeConfigMapChange(cb...)
	}
	defer func() { s.didWatch = true }()

	s.watchCtx = ctx
	chain, err := s.core.Nodes().Watch(ctx, v1.ListOptions{Watch: true})
	if err != nil {
		return err
	}
	s.GoWatch(ctx, EventBusConfigMapChangeKey, chain, cb...)
	return nil
}

// 获取ConfigMap列表
func (s *ConfigMap) GetConfigMaps(ctx context.Context, namespace string, req *v1.ListOptions) (*corev1.ConfigMapList, error) {
	return s.core.ConfigMaps(namespace).List(ctx, *req)
}

// 获取ConfigMap详情
func (s *ConfigMap) GetConfigMapDetails(ctx context.Context, namespace, name string) (*corev1.ConfigMap, error) {
	return s.core.ConfigMaps(namespace).Get(ctx, name, v1.GetOptions{})
}

// 创建ConfigMap
func (s *ConfigMap) CreateConfigMap(ctx context.Context, namespace string, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
	return s.core.ConfigMaps(namespace).Create(ctx, configMap, v1.CreateOptions{})
}

// 更新ConfigMap
func (s *ConfigMap) UpdateConfigMap(ctx context.Context, namespace string, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
	return s.core.ConfigMaps(namespace).Update(ctx, configMap, v1.UpdateOptions{})
}

// 删除ConfigMap
func (s *ConfigMap) DeleteConfigMap(ctx context.Context, namespace, name string) error {
	return s.core.ConfigMaps(namespace).Delete(ctx, name, v1.DeleteOptions{})
}
